package com.yang;

import com.yang.job.YangJobManager;
import com.yang.job.data.YangJobData;
import com.yang.job.enums.JobExecuteStrategyEnum;
import com.yang.job.execute.IYangJobExecutor;
import com.yang.job.execute.YangJobExecuteRequest;
import com.yang.job.factory.YangJobThreadFactory;
import com.yang.job.request.YangJobSubmitParam;
import com.yang.job.utils.CronUtils;
import com.yang.job.utils.FeaturesUtils;

import java.time.ZonedDateTime;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;

// Press Shift twice to open the Search Everywhere dialog and type `show whitespaces`,
// then press Enter. You can now see whitespace characters in your code.
public class Main {
    public static void main(String[] args) {
        YangJobData yangJobData = mockYangJobData();
        YangJobSubmitParam yangJobSubmitParam = convert2YangJobSubmitParam(yangJobData);

        YangJobManager yangJobManager = new YangJobManager.YangJobManagerBuilder()
                .setThreadFactory(new YangJobThreadFactory("yang"))
                .build();
        yangJobManager.submitJob(yangJobSubmitParam);

        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        yangJobManager.shutdown();
    }

    private static YangJobSubmitParam convert2YangJobSubmitParam(YangJobData yangJobData) {
        YangJobSubmitParam yangJobSubmitParam = new YangJobSubmitParam();
        yangJobSubmitParam.setJobId(yangJobData.getJobId());
        yangJobSubmitParam.setJobExecuteStrategy(JobExecuteStrategyEnum.getJobExecuteStrategyByName(yangJobData.getExecuteStrategy()));
        ZonedDateTime nextExecutionTime = CronUtils.nextExecutionTime(yangJobData.getCron(), ZonedDateTime.now());
        ZonedDateTime nextNextExecutionTime = CronUtils.nextExecutionTime(yangJobData.getCron(), nextExecutionTime);
        long nowEochMill = ZonedDateTime.now().toInstant().toEpochMilli();
        long executeEochMill = nextExecutionTime.toInstant().toEpochMilli();
        long secondExecuteEochMill = nextNextExecutionTime.toInstant().toEpochMilli();
        yangJobSubmitParam.setInitialDelay((int)(executeEochMill - nowEochMill) / 1000);
        yangJobSubmitParam.setPeriod((int)(secondExecuteEochMill - executeEochMill) / 1000);

        try {
            Class<?> aClass = Class.forName(yangJobData.getExecuteClassPath());
            if (!IYangJobExecutor.class.isAssignableFrom(aClass)) {
                throw new RuntimeException("任务类必须实现IYangJobExecutor接口");
            }
            IYangJobExecutor executor = (IYangJobExecutor) aClass.newInstance();
            YangJobExecuteRequest yangJobExecuteRequest = convert2YangJobExecuteRequest(yangJobData);
            Runnable runnable = () -> executor.execute(yangJobExecuteRequest);
            yangJobSubmitParam.setRunnable(runnable);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return yangJobSubmitParam;
    }

    private static YangJobExecuteRequest convert2YangJobExecuteRequest(YangJobData yangJobData) {
        YangJobExecuteRequest yangJobExecuteRequest = new YangJobExecuteRequest();
        yangJobExecuteRequest.setJobId(yangJobData.getJobId().toString());
        yangJobExecuteRequest.setParams(FeaturesUtils.convert2FeatureMap(yangJobData.getExecuteParams()));
        return yangJobExecuteRequest;
    }

    private static YangJobData mockYangJobData() {
        YangJobData yangJobData = new YangJobData();
        yangJobData.setJobId(1);
        yangJobData.setCron("0/5 * * * * ?");
        yangJobData.setExecuteStrategy(JobExecuteStrategyEnum.WITH_FIXED_DELAY.getName());
        yangJobData.setExecuteClassPath("com.yang.task.TestJobExecutor");
        yangJobData.setExecuteParams("jobId:1;startIndex:1;endIndex:10;");
        return yangJobData;
    }
//    public static void main(String[] args) {
//        ThreadFactory threadFactory = new YangJobThreadFactory("yang");
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4, threadFactory);
//
//        YangJobManager yangJobManager = new YangJobManager(scheduledExecutorService);
//        YangJobSubmitParam yangJobSubmitParam = new YangJobSubmitParam();
//        yangJobSubmitParam.setJobId(1);
//        yangJobSubmitParam.setRunnable(() -> System.out.println("执行任务=====" + new Date()));
//        yangJobSubmitParam.setInitialDelay(0);
//        yangJobSubmitParam.setPeriod(2);
//        yangJobSubmitParam.setJobExecuteStrategy(JobExecuteStrategyEnum.WITH_FIXED_RATE);
//        yangJobManager.submitJob(yangJobSubmitParam);
//
//        try {
//            Thread.sleep(10000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        System.out.println("取消任务==========");
//        yangJobManager.cancelJob(1);
//        try {
//            Thread.sleep(10000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        yangJobManager.shutdown();
//
//    }

//    public static void main(String[] args) {
//        ThreadFactory threadFactory = new YangJobThreadFactory("yang");
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4, threadFactory);
//        YangJobManager yangJobManager = new YangJobManager(scheduledExecutorService);
//
//        YangJobSubmitParam yangJobSubmitParam1 = new YangJobSubmitParam();
//        yangJobSubmitParam1.setRunnable(() -> System.out.println("立即执行======" + new Date()));
//        yangJobSubmitParam1.setJobExecuteStrategy(JobExecuteStrategyEnum.IMMEDIATE_EXECUTE);
//
//        YangJobSubmitParam yangJobSubmitParam2 = new YangJobSubmitParam();
//        yangJobSubmitParam2.setRunnable(() -> System.out.println("执行一次======" + new Date()));
//        yangJobSubmitParam2.setInitialDelay(1);
//        yangJobSubmitParam2.setJobExecuteStrategy(JobExecuteStrategyEnum.ONCE);
//
//        YangJobSubmitParam yangJobSubmitParam3 = new YangJobSubmitParam();
//        yangJobSubmitParam3.setRunnable(() -> System.out.println("withFixedDelay=====" + new Date()));
//        yangJobSubmitParam3.setInitialDelay(1);
//        yangJobSubmitParam3.setPeriod(2);
//        yangJobSubmitParam3.setJobExecuteStrategy(JobExecuteStrategyEnum.WITH_FIXED_DELAY);
//
//        YangJobSubmitParam yangJobSubmitParam4 = new YangJobSubmitParam();
//        yangJobSubmitParam4.setRunnable(() -> System.out.println("withFixedRate=====" + new Date()));
//        yangJobSubmitParam4.setInitialDelay(1);
//        yangJobSubmitParam4.setPeriod(2);
//        yangJobSubmitParam4.setJobExecuteStrategy(JobExecuteStrategyEnum.WITH_FIXED_RATE);
//
//        yangJobManager.schedule(yangJobSubmitParam1);
//        yangJobManager.schedule(yangJobSubmitParam2);
//        yangJobManager.schedule(yangJobSubmitParam3);
//        yangJobManager.schedule(yangJobSubmitParam4);
//
//        try {
//            Thread.sleep(20000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
//        yangJobManager.shutdown();
//    }

//    public static void main(String[] args) {
//        ThreadFactory threadFactory = new YangJobThreadFactory("yang");
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4, threadFactory);
//        YangJobManager yangJobManager = new YangJobManager(scheduledExecutorService, threadFactory);
//
//        yangJobManager.schedule(() -> {
//            System.out.println(Thread.currentThread().getName() + "schedule定时任务开始执行：" + new Date());
//        }, 1L);
//
//        yangJobManager.scheduleWithFixedDelay(() -> {
//            System.out.println(Thread.currentThread().getName() + "withFixedDelay定时任务开始执行：" + new Date());
//        }, 0L, 1L);
//
//        yangJobManager.scheduleWithFixedRate(() -> {
//            System.out.println(Thread.currentThread().getName() + "withFixedRate定时任务开始执行：" + new Date());
//        }, 0L, 1L);
//
//        try {
//            Thread.sleep(20000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
//        yangJobManager.shutdown();
//    }
}